﻿///////////////////////////////////////////////////////
//
// XDesigner.ORM 
//
// autohr : yuans
//
// date: 2011-2-23
//
// email  : yyf9989@hotmail.com
// 
//
///////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Text;
using XDesigner.ORM.DOM ;
using System.Collections;

namespace XDesigner.ORM
{
    public class ORMEventSender
    {
        public ORMEventSender()
        {
        }

        private ORMEngine _Engine = null;

        public ORMEngine Engine
        {
            get { return _Engine; }
            set { _Engine = value; }
        }

        private Dictionary<object, ORMEventHandler> _Handlers
            = new Dictionary<object, ORMEventHandler>();

        public void AddListener(object key, ORMEventHandler handler)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            this._Handlers[key] = handler;
        }

        public void RemoveListener(object key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            if ( this._Handlers.ContainsKey(key))
            {
                this._Handlers.Remove(key);
            }
        }

        public void Clear()
        {
            this._Handlers.Clear();
        }

        public void Broadcast(object sender, ORMEventArgs args)
        {
            ArrayList list = new ArrayList();
            list.AddRange(_Handlers.Values);
            if ( this._Handlers.ContainsKey(sender))
            {
                list.Remove( this._Handlers[sender]);
            }
            foreach (ORMEventHandler handler in list)
            {
                handler(sender, args);
            }
        }

        public void Send(object sender, ORMEventArgs args, object targetKey)
        {
            if (this._Handlers.ContainsKey(targetKey))
            {
                ORMEventHandler handle = _Handlers[targetKey];
                handle(sender, args);
            }
        }

    }//public class ORMEventSender

    public class ORMEventHandlerList
    {
        public ORMEventHandlerList()
        {
        }

        private ORMEngine _Engine = null;

        public ORMEngine Engine
        {
            get { return _Engine; }
            set { _Engine = value; }
        }

        private Dictionary<object, ORMEventHandler> _Handlers = new Dictionary<object, ORMEventHandler>();

        public ORMEventHandler this[object key ]
        {
            get
            {
                if (_Handlers.ContainsKey(key))
                {
                    return _Handlers[key];
                }
                else
                {
                    return null;
                }
            }
        }

        public void Add( object key , ORMEventHandler handler)
        {
            _Handlers[key] = handler;
        }

        public void Remove(object key )
        {
            _Handlers.Remove(key);
        }

        public void Clear()
        {
            _Handlers.Clear();
        }
         

        public object ExecuteCustomHandler(
            object key , 
            object instance, 
            ORMPropertyInfo property)
        {
            if (this.Engine == null)
            {
                throw new ArgumentNullException("engine");
            }
            ORMEventHandler handler = this[key];
            if (handler != null)
            {
                ORMEventArgs args = new ORMEventArgs(
                    new ORMContext(this.Engine ),
                    ORMEventStyle.Custom,
                    this.Engine.Project.Types[instance.GetType()]);
                args.Instance = instance;
                args.Property = property;
                handler(this, args);
                if (args.Context.Command != null)
                {
                    args.Context.Command.Dispose();
                }
                return args.Result;
            }
            return null;
        }

        public object BroadcstEvent(object sender , ORMEventStyle style, ORMTypeInfo type, object instance, ORMPropertyInfo property)
        {
            if (this.Engine == null)
            {
                throw new InvalidOperationException("Engine is null");
            }
            System.Collections.IEnumerable handlers = _Handlers.Values;
            ORMEventArgs args = new ORMEventArgs(new ORMContext(this.Engine), style, type);
            args.Instance = instance;
            args.Property = property;

            foreach (ORMEventHandler handler in handlers)
            {
                handler(sender, args);
            }
            if (args.Context.Command != null)
            {
                args.Context.Command.Dispose();
            }
            return args.Result;
        }
         
    }

    public delegate void ORMEventHandler( object sender , ORMEventArgs args );

    /// <summary>
    /// ORM event arguments
    /// </summary>
    public class ORMEventArgs : EventArgs
    {
        //public ORMEventArgs()
        //{
        //}

        public static ORMEventArgs CreateInstanceEvent(ORMContext context , object instance , ORMEventStyle style )
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }
            ORMEventArgs args = new ORMEventArgs(context, style, context.Engine.Project.Types[instance.GetType()]);
            args.Instance = instance;
            return args;
        }
         


        public ORMEventArgs(ORMEngine work, ORMEventStyle style)
        {
            _Engine = work;
            _Style = style;
        }

        public ORMEventArgs(ORMContext context, ORMEventStyle style, ORMTypeInfo type)
        {
            _Context = context;
            if (_Context != null)
            {
                _Engine = context.Engine;
            }
            _Style = style;
            _ORMType = type;
            if (_ORMType != null)
            {
                this._TableName = _ORMType.TableName;
            }
        }

        private ORMEngine _Engine = null;

        public ORMEngine Engine
        {
            get 
            { 
                return _Engine; 
            }
        }

        private ORMContext _Context = null;

        public ORMContext Context
        {
            get 
            {
                return _Context; 
            }
        }

        private ORMEventStyle _Style = ORMEventStyle.ReadInstance ;

        public ORMEventStyle Style
        {
            get
            { 
                return _Style; 
            }
        }

        private ORMTypeInfo _ORMType = null;

        public ORMTypeInfo ORMType
        {
            get 
            { 
                return _ORMType;
            }
        }


        private string _TableName = null;

        public string TableName
        {
            get
            {
                return _TableName; 
            }
        }


        private ORMPropertyInfo _Property = null;

        public ORMPropertyInfo Property
        {
            get
            {
                return _Property; 
            }
            set
            {
                _Property = value; 
            }
        }

        private object _Instance = null;

        public object Instance
        {
            get
            {
                return _Instance; 
            }
            set
            {
                _Instance = value; 
            }
        }

        private bool _Cancel = false;
        /// <summary>
        /// Flag that user cancel event
        /// </summary>
        public bool Cancel
        {
            get
            { 
                return _Cancel;
            }
            set
            {
                _Cancel = value;
            }
        }

        private object _Result = null;

        public object Result
        {
            get
            { 
                return _Result;
            }
            set
            { 
                _Result = value;
            }
        }
    }

    public enum ORMEventStyle
    {
        /// <summary>
        /// Read a instance from database
        /// </summary>
        ReadInstance,
        /// <summary>
        /// Insert a instance to database
        /// </summary>
        InsertInstance ,
        /// <summary>
        /// Delete a instance in database
        /// </summary>
        DeleteInstance ,
        /// <summary>
        /// Update a instance in database
        /// </summary>
        UpdateInstance,
        OpenConnection ,
        ExecuteCommand ,
        CloseConnection,
        Custom
    }
}
